#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>

struct ThreadInfo
{
  pthread_t tid;
  std::string name;
};

static const int defalutmum = 5;
template <class T>
class ThreadPool
{
public:
  void Lock()
  {
    pthread_mutex_lock(&mutex_); // 上锁
  }
  void Unlock()
  {
    pthread_mutex_unlock(&mutex_); // 解锁
  }

  void Wakeup()
  {
    pthread_cond_signal(&cond_); // 申请条件变量
  }
  void ThreadSleep()
  {
    pthread_cond_wait(&cond_, &mutex_); // 等待，同时释放锁
  }

  bool IsQueueEmpty()
  {
    return tasks_.empty();
  }
  std::string GetThreadName(pthread_t tid)
  {
    for (const auto &ti : threads_) // 遍历所有的线程
    {
      if (ti.tid == tid)
        return ti.name;
    }
    return "None"; // 找不到返回none
  }

public:
  static void *HandlerTask(void *args)
  {
    ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args); // 获取该参数并强转
    std::string name = tp->GetThreadName(pthread_self());
    while (true)
    {
      tp->Lock();
      while (tp->IsQueueEmpty())
      {
        tp->ThreadSleep();
      }
      // 如果不为空
      T t = tp->Pop(); // 扔出一个任务
      tp->Unlock();
      t(); // 执行任务
      std::cout << name << "run, " << "result: " << t.GetResult() << std::endl;
    }
  }

  void Start() // 启动线程池中的线程
  {
    int num = threads_.size();
    for (int i = 0; i < num; i++)
    {
      threads_[i].name = "thread-" + std::to_string(i + 1);           // 给线程起名字
      pthread_create(&(threads_[i].tid), nullptr, HandlerTask, this); // 创建线程，让它执行函数HandlerTask
    }
  }
  T Pop()
  {
    T t = tasks_.front();
    tasks_.pop();
    return t;
  }
  void Push(const T &t)
  {
    Lock();
    tasks_.push(t);
    Wakeup(); // 唤醒一个线程，然后来执行任务
    Unlock();
  }

  static ThreadPool<T> *GetInstance()
  {
    if (nullptr == tp_)
    {
      pthread_mutex_lock(&lock_);
      if (nullptr == tp_)
      {
        std::cout << "log::singleton create done first!" << std::endl;
        tp_ = new ThreadPool<T>(); // 如果为空，则创建新的线程池实例
      }
      pthread_mutex_unlock(&lock_);
    }
    return tp_;
  }

private:
  ThreadPool(int num = defalutmum) : threads_(num)
  {
    pthread_mutex_init(&mutex_, nullptr);
    pthread_cond_init(&cond_, nullptr);
  }
  ~ThreadPool()
  {
    pthread_mutex_destroy(&mutex_);
    pthread_cond_destroy(&cond_);
  }
  ThreadPool(const ThreadPool<T> &) = delete;
  const ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;

private:
  std::vector<ThreadInfo> threads_;
  std::queue<T> tasks_;

  pthread_mutex_t mutex_; // 锁
  pthread_cond_t cond_;   // 条件变量

  static ThreadPool<T> *tp_; // 这个指针用来存储threadPool类的唯一实例的地址，这是实现单例模式的关键。

  static pthread_mutex_t lock_;
};
template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr; // 这两行是静态成员变量的声明

template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;